﻿#include "MySQLDB.h"

MySQLDB::MySQLDB(const std::string& host,
                 unsigned int port,
                 const std::string& user,
                 const std::string& password,
                 const std::string& database)
        : host_(host), port_(port), user_(user), password_(password), database_(database) {}

MySQLDB::~MySQLDB() {
    if (session_) {
        session_->close();
    }
}

// 连接数据库
bool MySQLDB::connect() {
    try {
        session_ = std::make_unique<mysqlx::Session>(host_, port_, user_, password_);
        // 测试获取 schema 是否成功
        session_->getSchema(database_);
        return true;
    } catch (const mysqlx::Error& err) {
        std::cerr << "Connection error: " << err.what() << std::endl;
        return false;
    } catch (std::exception& ex) {
        std::cerr << "STD exception: " << ex.what() << std::endl;
        return false;
    }
}

// 查询
std::vector<std::map<std::string, std::string>> MySQLDB::query(
        const std::string& tableName,
        const std::vector<std::string>& columns,
        const std::string& whereClause)
{
    std::vector<std::map<std::string, std::string>> results;
    try {
        auto table = session_->getSchema(database_).getTable(tableName);

        mysqlx::RowResult res;
        if (whereClause.empty()) {
            res = table.select(columns).execute();
        } else {
            res = table.select(columns).where(whereClause).execute();
        }

        for (auto row : res) {
            std::map<std::string, std::string> rowMap;
            for (size_t i = 0; i < columns.size(); ++i) {
                rowMap[columns[i]] = row[i].get<std::string>();
            }
            results.push_back(rowMap);
        }
    } catch (const mysqlx::Error& err) {
        std::cerr << "Query error: " << err.what() << std::endl;
    }
    return results;
}

// 插入
bool MySQLDB::insert(const std::string& tableName, const std::map<std::string, std::string>& data) {
    try {
        auto table = session_->getSchema(database_).getTable(tableName);
        std::vector<std::string> columns;
        std::vector<mysqlx::Value> values;

        for (auto& kv : data) {
            columns.push_back(kv.first);
            values.push_back(kv.second);
        }

        table.insert(columns).values(values).execute();
        return true;
    } catch (const mysqlx::Error& err) {
        std::cerr << "Insert error: " << err.what() << std::endl;
        return false;
    }
}

// 更新
bool MySQLDB::update(const std::string& tableName,
                     const std::map<std::string, std::string>& data,
                     const std::string& whereClause)
{
    try {
        auto table = session_->getSchema(database_).getTable(tableName);
        auto upd = table.update();
        for (auto& kv : data) {
            upd.set(kv.first, kv.second);
        }
        if (!whereClause.empty()) {
            upd.where(whereClause);
        }
        upd.execute();
        return true;
    } catch (const mysqlx::Error& err) {
        std::cerr << "Update error: " << err.what() << std::endl;
        return false;
    }
}

// 删除
bool MySQLDB::remove(const std::string& tableName, const std::string& whereClause) {
    try {
        auto table = session_->getSchema(database_).getTable(tableName);
        auto rm = table.remove();
        if (!whereClause.empty()) {
            rm.where(whereClause);
        }
        rm.execute();
        return true;
    } catch (const mysqlx::Error& err) {
        std::cerr << "Delete error: " << err.what() << std::endl;
        return false;
    }
}
